{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "41f6cffa-250e-4aae-9821-48d73e3bfa8d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# 本节大纲\n",
    "\n",
    "1. 版本介绍，15分钟\n",
    "2. 提示词工程优化，10分钟\n",
    "3. 嵌入模型，20分钟\n",
    "4. 向量数据库，30分钟\n",
    "5. 工程化开发，30分钟\n",
    "6. 答疑和总结，15分钟"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3cdb75cc-4224-4065-908b-baad9ea8decd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "bd043ecf-18bc-4ce0-8d1d-eeb0160118e7",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting pinecone-client\n",
      "  Obtaining dependency information for pinecone-client from https://files.pythonhosted.org/packages/df/d4/cffbb61236c6c1d7510e835c1ff843e4e7d705ed59d21c0e5b6dc1cb4fd8/pinecone_client-2.2.4-py3-none-any.whl.metadata\n",
      "  Downloading pinecone_client-2.2.4-py3-none-any.whl.metadata (7.8 kB)\n",
      "Requirement already satisfied: requests>=2.19.0 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.31.0)\n",
      "Requirement already satisfied: pyyaml>=5.4 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (6.0.1)\n",
      "Collecting loguru>=0.5.0 (from pinecone-client)\n",
      "  Obtaining dependency information for loguru>=0.5.0 from https://files.pythonhosted.org/packages/03/0a/4f6fed21aa246c6b49b561ca55facacc2a44b87d65b8b92362a8e99ba202/loguru-0.7.2-py3-none-any.whl.metadata\n",
      "  Downloading loguru-0.7.2-py3-none-any.whl.metadata (23 kB)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (4.7.1)\n",
      "Collecting dnspython>=2.0.0 (from pinecone-client)\n",
      "  Obtaining dependency information for dnspython>=2.0.0 from https://files.pythonhosted.org/packages/f6/b4/0a9bee52c50f226a3cbfb54263d02bb421c7f2adc136520729c2c689c1e5/dnspython-2.4.2-py3-none-any.whl.metadata\n",
      "  Downloading dnspython-2.4.2-py3-none-any.whl.metadata (4.9 kB)\n",
      "Requirement already satisfied: python-dateutil>=2.5.3 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.8.2)\n",
      "Requirement already satisfied: urllib3>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.0.4)\n",
      "Requirement already satisfied: tqdm>=4.64.1 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (4.66.1)\n",
      "Requirement already satisfied: numpy>=1.22.0 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (1.25.2)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.11/site-packages (from python-dateutil>=2.5.3->pinecone-client) (1.16.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pinecone-client) (3.2.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pinecone-client) (3.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pinecone-client) (2023.7.22)\n",
      "Downloading pinecone_client-2.2.4-py3-none-any.whl (179 kB)\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m179.4/179.4 kB\u001B[0m \u001B[31m24.4 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n",
      "\u001B[?25hDownloading dnspython-2.4.2-py3-none-any.whl (300 kB)\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m300.4/300.4 kB\u001B[0m \u001B[31m50.5 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n",
      "\u001B[?25hDownloading loguru-0.7.2-py3-none-any.whl (62 kB)\n",
      "\u001B[2K   \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m62.5/62.5 kB\u001B[0m \u001B[31m19.3 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n",
      "\u001B[?25hInstalling collected packages: loguru, dnspython, pinecone-client\n",
      "Successfully installed dnspython-2.4.2 loguru-0.7.2 pinecone-client-2.2.4\n"
     ]
    }
   ],
   "source": [
    "!pip install pinecone-client tiktoken"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe102593-de6b-4128-91cb-953f1b07e694",
   "metadata": {},
   "source": [
    "### 小墨 v0.2 介绍"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38be0b71-9138-48ec-baf7-109d296bfc72",
   "metadata": {},
   "source": [
    "![v0.2](./resource/images/v0.2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93cc3989-0aa1-44fa-92de-79de97219165",
   "metadata": {},
   "source": [
    "### 提示词工程优化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "f836c800-4f3f-442c-8aaf-127f17a18305",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 回顾下上周\n",
    "# 通过 Prompt 的方式让 小墨可以回答出 墨问西东最帅的男人"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a83a7019-34cf-48ff-8d09-00e19936a85b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4d208a1c-ff07-4704-a3f0-9a5a79407970",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ChatCompletion(system_prompt, user_prompt, top_p=1, temperature=0, max_tokens=2048):\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=\"gpt-3.5-turbo-0613\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_prompt},\n",
    "        ],\n",
    "        top_p=top_p,\n",
    "        temperature=temperature, \n",
    "        max_tokens=max_tokens,\n",
    "    )\n",
    "    return response"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "faa5ed14-70d4-47cc-9acb-b4054bf9c81b",
   "metadata": {},
   "source": [
    "#### 没有任何的系统提示词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b3c94288-2d9c-4046-b5f8-40c806035813",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'我是一个人工智能助手，被称为OpenAI GPT-3。我被设计用来回答各种问题和提供信息。有什么我可以帮助你的吗？'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "system_prompt = \"\"\n",
    "user_prompt = \"你是谁\"\n",
    "\n",
    "ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92d1c6e0-0c31-48f8-a0d7-c221162eeeb4",
   "metadata": {},
   "source": [
    "#### 加上一条系统提示词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "22e3a2ce-b8d5-4b8d-b32c-c51a5141a5a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'我是一个由墨问西东打造的问答机器人。'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "system_prompt = \"当你被人问起身份时，你必须用'我是一个由墨问西东打造的问答机器人'回答。例如问题 [你好，你是谁，你是谁开发的，你和GPT有什么关系，你和OpenAI有什么关系]\"\n",
    "user_prompt = \"你是谁\"\n",
    "\n",
    "ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a37d4676-e5ea-4288-aa66-eea79f22452c",
   "metadata": {},
   "source": [
    "#### 如果有很多条数据作为提示词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "469d80d0-67ba-4d89-aec9-ea2cb24b85f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'我是一个由墨问西东打造的问答机器人，瑶瑶是墨问西东颜值担当，遥遥领先。'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "system_prompt = \"当你被人问起身份时，你必须用'我是一个由墨问西东打造的问答机器人'回答。例如问题 [你好，你是谁，你是谁开发的，你和GPT有什么关系，你和OpenAI有什么关系]\"\n",
    "user_prompt = \"\"\"\n",
    "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
    "Q: 小盖是谁 A: 小盖是墨问西东最帅的男人。\n",
    "Q: 瑶瑶是谁 A: 瑶瑶是墨问西东颜值担当，遥遥领先。\n",
    "\n",
    "用户问题：瑶瑶是谁\n",
    "\"\"\"\n",
    "\n",
    "ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b41d30e7-3a8f-4cc2-b73a-8dc5fbdf4a64",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 由于 LLM 对于输入的 Token 是有限制的，我们无法把大量的数据放去提示词\n",
    "# 人工去维护提示词，成本太高，而且不优雅"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5166ca69-5074-462c-b4a9-ffa382f5ccb3",
   "metadata": {},
   "source": [
    "#### 提示词中的知识库是根据问题去搜索得到"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "8d5df72f-9e13-47aa-96e4-304c554237d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "user_prompt = \"\"\"\n",
    "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
    "{knowledge_base}\n",
    "\n",
    "用户问题：瑶瑶是谁\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "1ae52a3e-52d9-41b9-b7b9-29a4b2376161",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
      "\n",
      "Q: 小盖是谁 A: 小盖是墨问西东最帅的男人。\n",
      "\n",
      "\n",
      "用户问题：瑶瑶是谁\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 知识库只提供一条数据\n",
    "knowledge_base = \"\"\"\n",
    "Q: 小盖是谁 A: 小盖是墨问西东最帅的男人。\n",
    "\"\"\"\n",
    "\n",
    "print(user_prompt.format(knowledge_base=knowledge_base))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "fed63448-992a-4324-9a72-b352e8a68c64",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
      "\n",
      "Q: 小盖是谁 A: 小盖是墨问西东最帅的男人。\n",
      "\n",
      "      ... 省略n条相关知识 ...\n",
      "      \n",
      "Q: 瑶瑶是谁 A: 瑶瑶是墨问西东颜值担当，遥遥领先。\n",
      "\n",
      "\n",
      "用户问题：瑶瑶是谁\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 知识库提供了若干条数据\n",
    "\n",
    "knowledge_base = \"\"\"\n",
    "Q: 小盖是谁 A: 小盖是墨问西东最帅的男人。\n",
    "\n",
    "      ... 省略n条相关知识 ...\n",
    "      \n",
    "Q: 瑶瑶是谁 A: 瑶瑶是墨问西东颜值担当，遥遥领先。\n",
    "\"\"\"\n",
    "\n",
    "print(user_prompt.format(knowledge_base=knowledge_base))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a58fb0e9-2e72-4b3c-ad03-15463f6f7f9d",
   "metadata": {},
   "source": [
    "#### 为什么不直接通过检索/推荐的方式返回，而要经过大语言模型在处理一次"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "b4c7c568-76e7-44de-a97a-26e3a89bae70",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 假设向量数据库只有2条数据\n",
    "# 就算检索在极致，也是无法回答到用户问题\n",
    "\n",
    "knowledge_base = [\n",
    "    {\"Question\": \"小盖是谁\", \"Answer\": \"小盖是墨问西东最帅的男人。\"},\n",
    "    {\"Question\": \"瑶瑶是谁\", \"Answer\": \"瑶瑶是墨问西东的颜值担当，遥遥领先。\"},\n",
    "]\n",
    "\n",
    "user_prompt = \"用户问题：瑶瑶和小盖是什么关系\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "782381f0-e6ee-4838-8e75-e63c4641d8b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小盖是墨问西东最帅的男人。\n"
     ]
    }
   ],
   "source": [
    "# 当向量数据库检索返回第一个答案\n",
    "print(knowledge_base[0]['Answer'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "8426939a-4af4-487d-983d-70fccecfb12b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "瑶瑶是墨问西东的颜值担当，遥遥领先。\n"
     ]
    }
   ],
   "source": [
    "# 当向量数据库检索返回第二个答案\n",
    "print(knowledge_base[1]['Answer'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "02ac30b2-5701-4b22-afc3-dbdb78ccdeb2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'瑶瑶和小盖是墨问西东团队中的成员，他们是同事关系。'"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如果有了大语言模型\n",
    "# 发挥推理能力，就可以联系到墨问西东是他们共同的标签\n",
    "\n",
    "user_prompt = \"\"\"\n",
    "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
    "{knowledge_base}\n",
    "\n",
    "用户问题：瑶瑶和小盖是什么关系\n",
    "\"\"\"\n",
    "\n",
    "user_prompt = user_prompt.format(knowledge_base=knowledge_base)\n",
    "\n",
    "ChatCompletion(\"\", user_prompt)[\"choices\"][0][\"message\"][\"content\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9c1aad9-ebb3-4619-8696-fc35e3f76bf4",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# LangSmith\n",
    "# https://smith.langchain.com/\n",
    "# 目前还是需要邀请码，或者通过等待名单，一个提示词的调试利器。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27aed520-b00e-4f42-aeaf-24c13f3da180",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f681ef0-ef40-48bd-8b3e-d5f3735ec878",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db8ecb48-9fe8-447c-9fa8-2bc38cf8c9fb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d956daa-3ef9-4ded-8a4e-4f451ccd9fe6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6267ac6-169f-4780-b23e-f2708c3db929",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2cdadf7a-6f5e-4f4d-8e9c-56b4d74d6d50",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19a9a448-adb0-4502-a2c8-63c07d6d472d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "26e419cf-998f-42b5-a520-fb4816050728",
   "metadata": {},
   "source": [
    "### 所以向量数据库很重要，大语言模型也很重要"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8b3cdca-05ee-41e9-b078-f52f79c773d1",
   "metadata": {},
   "source": [
    "#### 什么是向量？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "41c8bfdb-01f5-4af4-ba65-6747b2f4dcd2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dimension: 8\n"
     ]
    }
   ],
   "source": [
    "# 在数学上，表示有方向的值\n",
    "vector = [0, 1, 0, -1, -1, 0, 1, -1]\n",
    "print(\"Dimension:\", len(vector))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59d158de-f441-49aa-8c98-d75e753a41f9",
   "metadata": {},
   "source": [
    "#### 如何向量化？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84e8b1f1-daed-4fe0-811f-f1154d4e3089",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# OpenAI Embedding Model\n",
    "# https://platform.openai.com/docs/guides/embeddings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "53e5c622-e3d5-4cd1-bb6e-e05ebc480dea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用嵌入模型，把任意的输入(文本、图片、音乐..)，变成一个向量\n",
    "\n",
    "response = openai.Embedding.create(\n",
    "  model=\"text-embedding-ada-002\",\n",
    "  input=[\"May i have you name?\"]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "d20fdfc2-8548-48d1-ab3f-15eb2df9df03",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dimension: 1536\n"
     ]
    }
   ],
   "source": [
    "print(\"Dimension:\", len(response['data'][0]['embedding']))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23823b7e-0545-4d25-84f5-2f43249f1149",
   "metadata": {},
   "source": [
    "#### 基于向量如何实现查询？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "1d82f663-cfb7-417c-a9ff-3556f643f9bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用嵌入模型，把知识库里的文本变成向量\n",
    "\n",
    "knowledge_base = [\"Hello\", \"Bonjour\", \"你好\", \"小盖是墨问西东最帅的男人\", \"瑶瑶是墨问西东的颜值担当\"]\n",
    "\n",
    "response = openai.Embedding.create(\n",
    "  model=\"text-embedding-ada-002\",\n",
    "  input=knowledge_base\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "d8bd252f-5b2d-4c2d-93c9-4bf0002660bb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第 0 个向量，有 1536 维度。\n",
      "第 1 个向量，有 1536 维度。\n",
      "第 2 个向量，有 1536 维度。\n",
      "第 3 个向量，有 1536 维度。\n",
      "第 4 个向量，有 1536 维度。\n",
      "全部有 5 个向量。\n"
     ]
    }
   ],
   "source": [
    "for i in range(len(response['data'])):\n",
    "    print(f\"第 {i} 个向量，有 {len(response['data'][i]['embedding'])} 维度。\")\n",
    "print(f\"全部有 {len(response['data'])} 个向量。\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "e3f0cbf4-f69c-4e9e-96f6-6f58a2a935f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先把向量转成可计算的 Numpy 格式\n",
    "import numpy as np\n",
    "\n",
    "vector_list = []\n",
    "for item in response['data']:\n",
    "    vector_list.append(np.array(item['embedding']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 214,
   "id": "1b5b9eb3-dc9e-495b-a8bc-788e69ccee09",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 214,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(vector_list[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "75ed9bad-04ce-40f7-82da-d2342fa093be",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用嵌入模型，把用户要查询的问题变成向量\n",
    "\n",
    "question = \"小盖是谁\"\n",
    "\n",
    "response = openai.Embedding.create(\n",
    "  model=\"text-embedding-ada-002\",\n",
    "  input=question\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "5b270e36-cbd6-40bb-962f-c4f9e0a4143b",
   "metadata": {},
   "outputs": [],
   "source": [
    "vector = np.array(response['data'][0]['embedding'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "986e7145-81af-41f6-adbe-66f7fcde3090",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.74063029, 0.74577651, 0.65737027, 0.4619709 , 0.65198182])"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 相似度计算（距离越小，代表相似度越高）\n",
    "l2_distance_list = np.linalg.norm((vector - vector_list), axis=1)\n",
    "l2_distance_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "39d1656c-2d61-4834-9e88-8cfebb0360ab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户输入的问题是: 小盖是谁\n",
      "检索到最相似的文本是: 小盖是墨问西东最帅的男人\n",
      "距离是: 0.46197089689872767\n"
     ]
    }
   ],
   "source": [
    "# 找出最相似的原始文本（最小值的下标，然后去匹配文本）\n",
    "min_index = np.argmin(l2_distance_list)\n",
    "\n",
    "print(f\"用户输入的问题是: {question}\\n检索到最相似的文本是: {knowledge_base[min_index]}\\n距离是: {l2_distance_list[min_index]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "018b4218-d6fc-4f7b-99d4-baf2a98f74ac",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77387124-ea32-4217-87c9-4830ed7026cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dba7b4c6-626b-41c6-9d82-32d3e0fc1e21",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3ea3071-ca14-4b3f-b2ca-7781b7c4ff08",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de02f752-f758-4aa0-8044-08056623aa1b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d549b0f0-e5c4-4817-bce3-43e8a192aa70",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a03245d-80ed-4d3e-b26b-6da2411e0a58",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f14af455-6060-4b23-9ec5-5717f83fbaec",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2b27dc06-4e34-4b4a-bc9f-f58d3ceedc4d",
   "metadata": {},
   "source": [
    "### 好了，我们也知道向量检索是咋一回事，接下来接入向量数据库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "afc726b7-ddbd-42cf-bab6-4dc5ebfd80f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Pinecone (SaaS API)\n",
    "# https://www.pinecone.io/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24d303cc-24bd-4832-b4ba-47e51cb6a562",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化对象\n",
    "import pinecone      \n",
    "\n",
    "pinecone.init(      \n",
    "\tapi_key='replace to your api key',\n",
    "\tenvironment='asia-southeast1-gcp-free'      \n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f608d71c-1674-4b62-9196-6e5602d20bd3",
   "metadata": {},
   "source": [
    "#### 数据库的操作其实很简单"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0109924f-3ba3-4b96-9f1b-d5ef65f0ca8f",
   "metadata": {},
   "source": [
    "##### 创建索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "id": "0a51de54-e8ed-4d7f-91c1-40965747becf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# dimension 指的是向量的维度，在一开始就要考虑好\n",
    "pinecone.create_index(\"mobot\", dimension=1536)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "475129ef-034a-44c9-ae9e-2f756f86efa5",
   "metadata": {},
   "source": [
    "##### 列出所有索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "bb63b987-7120-42b3-9cbf-c1d3d8180e9f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['mobot']"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pinecone.list_indexes()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7c607ae-28f2-4289-a027-075943b0435c",
   "metadata": {},
   "source": [
    "##### 查看索引描述"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "id": "af7054f5-875c-4136-b92c-63f55af015f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IndexDescription(name='mobot', metric='cosine', replicas=1, dimension=1536.0, shards=1, pods=1, pod_type='p1', status={'ready': True, 'state': 'Ready'}, metadata_config=None, source_collection='')"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pinecone.describe_index(\"mobot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f542dc2c-5452-4a09-b057-ab639f886b15",
   "metadata": {},
   "source": [
    "##### 删除索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4d1566f-7087-408e-bfb7-82698c1e4395",
   "metadata": {},
   "outputs": [],
   "source": [
    "pinecone.delete_index(\"mobot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25e52b86-ea44-4075-bbcd-aa3e40bf77d3",
   "metadata": {},
   "source": [
    "##### 查看索引统计"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "426bafad-8ce2-466f-8f81-2b15fa00e855",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'dimension': 1536,\n",
       " 'index_fullness': 0.0,\n",
       " 'namespaces': {},\n",
       " 'total_vector_count': 0}"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index = pinecone.Index(\"mobot\")\n",
    "index.describe_index_stats()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78e7cb1c-552b-4e5b-be89-26e7d1b38377",
   "metadata": {},
   "source": [
    "##### 增加或覆盖数据 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "id": "b8c5a44a-fd7e-4725-af40-4002179fe984",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 把文本向量化\n",
    "\n",
    "def embedding(text):\n",
    "    response = openai.Embedding.create(\n",
    "      model=\"text-embedding-ada-002\",\n",
    "      input=[text]\n",
    "    )\n",
    "    # 只需要返回向量\n",
    "    return response['data'][0]['embedding']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "id": "99559224-2cd7-4f9e-b655-8153f5d35617",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'upserted_count': 3}"
      ]
     },
     "execution_count": 185,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knowledge_base = [\n",
    "    {\"system\": \"mobot\", \"question\": \"小盖是谁\", \"answer\": \"小盖是墨问西东最帅的男人。\"},\n",
    "    {\"system\": \"mobot\", \"question\": \"瑶瑶是谁\", \"answer\": \"瑶瑶是墨问西东的颜值担当，遥遥领先。\"},\n",
    "    {\"system\": \"wenbot\", \"question\": \"皮肤很干燥\", \"answer\": \"这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。\"}\n",
    "]\n",
    "\n",
    "\n",
    "index.upsert(\n",
    "    vectors=[\n",
    "        (\n",
    "         \"1\",                                       # Vector ID \n",
    "         embedding(knowledge_base[0]['question']),  # Dense vector values\n",
    "         knowledge_base[0]                          # Vector metadata\n",
    "        ),\n",
    "        (\n",
    "         \"2\",                                       # Vector ID \n",
    "         embedding(knowledge_base[1]['question']),  # Dense vector values\n",
    "         knowledge_base[1]                          # Vector metadata\n",
    "        ),\n",
    "        ( \n",
    "         \"3\",                                       # Vector ID \n",
    "         embedding(knowledge_base[2]['question']),  # Dense vector values\n",
    "         knowledge_base[2]                          # Vector metadata\n",
    "        )\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5589e81d-308a-4d34-85da-1bbbee8b5870",
   "metadata": {},
   "source": [
    "##### 相似度搜索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "id": "a2919d23-c9e3-497f-9b68-115de377be02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'matches': [{'id': '2',\n",
       "              'metadata': {'answer': '瑶瑶是墨问西东的颜值担当，遥遥领先。',\n",
       "                           'question': '瑶瑶是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.871682763,\n",
       "              'values': []},\n",
       "             {'id': '1',\n",
       "              'metadata': {'answer': '小盖是墨问西东最帅的男人。',\n",
       "                           'question': '小盖是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.77723223,\n",
       "              'values': []},\n",
       "             {'id': '3',\n",
       "              'metadata': {'answer': '这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。',\n",
       "                           'question': '皮肤很干燥',\n",
       "                           'system': 'wenbot'},\n",
       "              'score': 0.740868449,\n",
       "              'values': []}],\n",
       " 'namespace': ''}"
      ]
     },
     "execution_count": 162,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "question = \"你给我介绍一下瑶瑶\"\n",
    "\n",
    "index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=embedding(question)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "id": "15ef09a2-3c60-4f2a-82b1-05f48be7bd94",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 很好，得分最高的记录就是我们想要的\n",
    "# 但是，把另外一个系统的数据也检索出来了（多租户时）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "feef87e9-d0fa-4630-a674-3a1c3f296b23",
   "metadata": {},
   "source": [
    "##### 混合搜素（标量+向量）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "id": "c0814a60-4ed6-4055-898c-536cbccab91c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'matches': [{'id': '2',\n",
       "              'metadata': {'answer': '瑶瑶是墨问西东的颜值担当，遥遥领先。',\n",
       "                           'question': '瑶瑶是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.871682763,\n",
       "              'values': []},\n",
       "             {'id': '1',\n",
       "              'metadata': {'answer': '小盖是墨问西东最帅的男人。',\n",
       "                           'question': '小盖是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.77723223,\n",
       "              'values': []}],\n",
       " 'namespace': ''}"
      ]
     },
     "execution_count": 164,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "question = \"你给我介绍一下瑶瑶\"\n",
    "\n",
    "index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=embedding(question),\n",
    "    filter={\n",
    "        \"system\": \"mobot\"\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "id": "62495c81-cfed-40d2-a884-df1526d2ae74",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'matches': [{'id': '3',\n",
       "              'metadata': {'answer': '这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。',\n",
       "                           'question': '皮肤很干燥',\n",
       "                           'system': 'wenbot'},\n",
       "              'score': 0.920912206,\n",
       "              'values': []}],\n",
       " 'namespace': ''}"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "question = \"我的皮肤好干，该怎么办啊\"\n",
    "\n",
    "index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=embedding(question),\n",
    "    filter={\n",
    "        \"system\": {\"$in\": [\"wenbot\"]}\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e62c672-ff5a-4208-9175-0c68ad85022e",
   "metadata": {},
   "source": [
    "##### 删除数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "id": "c1545077-c8a6-4a78-b6e1-e2569eeabeb3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'answer': '瑶瑶是墨问西东的颜值担当，遥遥领先。', 'question': '瑶瑶是谁', 'system': 'mobot'}"
      ]
     },
     "execution_count": 177,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = index.fetch(\n",
    "    ids=[\"2\"]\n",
    ")\n",
    "\n",
    "result['vectors']['2']['metadata']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "id": "1b2117ad-6715-418b-b862-e1018f7a31b6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": 179,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index.delete(ids=[\"2\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 180,
   "id": "6ed8f879-5724-47dd-a403-4e6c7623ac9f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'namespace': '', 'vectors': {}}"
      ]
     },
     "execution_count": 180,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "index.fetch(ids=[\"2\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fcf23119-66b4-431c-8f6f-2d621f03023b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8877aacf-eff9-4d56-8f42-a5e5e48a6059",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bfb34fd-08e0-4680-8882-486a675a58e7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fab387d-fa04-4dd2-8f91-2730c32ff199",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b1af68e-5915-44a3-a2c4-8f9d6a35f492",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "520cb26c-b883-4c0d-b11c-d06167ffe214",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e71ff092-54a1-485d-8a95-8dbebfa084af",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f09ede83-2768-4bb1-a777-e5f27961f2ce",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "64d7425b-6a36-40ff-a0f8-6436842c2b6d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b245a127-cc78-4185-af71-6dfac898408b",
   "metadata": {},
   "source": [
    "### 掌握了向量数据库的操作，来模拟下检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "id": "e1ecde81-962d-4725-a1f3-4b01fbf43afb",
   "metadata": {},
   "outputs": [],
   "source": [
    "question = \"你给我介绍一下瑶瑶\"\n",
    "\n",
    "response = index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=embedding(question)\n",
    ")\n",
    "\n",
    "answer = response['matches'][0]['metadata']['answer']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "id": "2b9c3331-c450-4ea7-affe-98d97bf543a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户提问: 你给我介绍一下瑶瑶\n",
      "小墨回答: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n"
     ]
    }
   ],
   "source": [
    "print(f'用户提问: {question}\\n小墨回答: {answer}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f4a8a49-326a-47d7-b3de-2c9100817dfd",
   "metadata": {},
   "source": [
    "#### 换个问题，在来一次"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 199,
   "id": "c3a15aab-bb1d-4eef-a004-c30ce77260b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "question = \"瑶瑶和小盖是什么关系\"\n",
    "\n",
    "response = index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=embedding(question)\n",
    ")\n",
    "\n",
    "answer = response['matches'][0]['metadata']['answer']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 196,
   "id": "53085dd7-e8cb-4cf9-a62d-98072cfce52d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户提问: 瑶瑶和小盖是什么关系\n",
      "小墨回答: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n"
     ]
    }
   ],
   "source": [
    "print(f'用户提问: {question}\\n小墨回答: {answer}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 200,
   "id": "3b079b60-5a21-4677-a9a7-07b52990cd85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'matches': [{'id': '2',\n",
       "              'metadata': {'answer': '瑶瑶是墨问西东的颜值担当，遥遥领先。',\n",
       "                           'question': '瑶瑶是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.876494884,\n",
       "              'values': []},\n",
       "             {'id': '1',\n",
       "              'metadata': {'answer': '小盖是墨问西东最帅的男人。',\n",
       "                           'question': '小盖是谁',\n",
       "                           'system': 'mobot'},\n",
       "              'score': 0.856307,\n",
       "              'values': []},\n",
       "             {'id': '3',\n",
       "              'metadata': {'answer': '这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。',\n",
       "                           'question': '皮肤很干燥',\n",
       "                           'system': 'wenbot'},\n",
       "              'score': 0.731672585,\n",
       "              'values': []}],\n",
       " 'namespace': ''}"
      ]
     },
     "execution_count": 200,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08e7935d-a8db-4299-8a10-022462ba5828",
   "metadata": {},
   "source": [
    "#### 必须大模型出场了，加持一下"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "id": "41a1b55e-e85e-4dba-9068-8ed2901cc44f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
      "question: 瑶瑶是谁 answer: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "question: 小盖是谁 answer: 小盖是墨问西东最帅的男人。\n",
      "question: 皮肤很干燥 answer: 这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。\n",
      "\n",
      "\n",
      "用户问题：瑶瑶和小盖是什么关系\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 拼接一下检索到的数据\n",
    "knowledge_base = \"\"\n",
    "\n",
    "for item in response['matches']:\n",
    "    knowledge_base += (f'question: {item[\"metadata\"][\"question\"]} answer: {item[\"metadata\"][\"answer\"]}\\n')\n",
    "\n",
    "\n",
    "user_prompt_template = \"\"\"\n",
    "当用户问到问题时，你可以参考知识库内的答案提供回复：\n",
    "{knowledge_base}\n",
    "\n",
    "用户问题：{question}\n",
    "\"\"\"\n",
    "\n",
    "user_prompt = user_prompt_template.format(question=question, knowledge_base=knowledge_base)\n",
    "print(user_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "id": "58af67bb-2a9e-4e80-8a17-9c6dc876d27b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'瑶瑶和小盖是墨问西东团队中的成员，他们是同事关系。瑶瑶是墨问西东的颜值担当，而小盖则是墨问西东团队中最帅的男人。'"
      ]
     },
     "execution_count": 209,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ChatCompletion(\"\", user_prompt)[\"choices\"][0][\"message\"][\"content\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28be4a81-4d25-4f0e-95ef-9a3c41e85ae6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9cb3d3b-99f1-4962-bfb3-30e203725e69",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2fa99ae1-52a9-4724-bb56-4b0815c0bb67",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7b447f9-79e9-4d4e-b8f9-bd163388c8aa",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "607b64f9-85d1-41b1-a532-f61343e71fd8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f16bef6-5b3b-4d56-82ed-22d0bce3701e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c982d2ab-66be-4e8b-a661-02f79c07ab4c",
   "metadata": {},
   "source": [
    "### 非常好，那就开始工程化集成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd485654-d31a-40ae-94d4-ca0f30fe1f11",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 上代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c39c779-0f34-47d2-b6c8-c1d33e9ad863",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea17a037-8969-46ad-b5ef-4ba57119cfcf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f0bdc5a-c9f2-4825-9450-e6905bcf2783",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
